#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>
#include <ctype.h>
#include <arpa/inet.h>
#include "wrap.h"

#define MAXLINE 8192
#define SERV_PORT 7777

struct s_info{
    struct sockaddr_in cliaddr;
    int connfd;
};

void *do_work(void *arg){
    int n,i;
    struct s_info *ts = (struct s_info*)arg;
    char buf[MAXLINE];
    char str[INET_ADDRSTRLEN]; //#define INET_ADDRSTRLEN 16
    while(1){
        n = Read(ts->connfd,buf,MAXLINE);
        if(n == 0){
            printf("the client %d closed ... \n",ts->connfd);
            break;
        }
        printf("reveive from %s at port %d\n",inet_ntop(AF_INET,&(*ts).cliaddr.sin_addr.s_addr,str,sizeof(str)),ntohs((*ts).cliaddr.sin_port));
        for(i=0; i < n; i++){
            buf[i]=toupper(buf[i]);
        }

        Write(STDOUT_FILENO,buf,n);
        Write(ts->connfd,buf,n);
    }
    Close(ts->connfd);
    return (void*)0;
}


int main(){
    struct sockaddr_in server_sockaddr;
    pthread_t tid;

    struct s_info ts[256];

    //memset(&server_scokaddr,0,sizeof(server_sockaddr)); //将结构地址清0
    bzero(&server_sockaddr,sizeof(server_sockaddr));

    int s_fd = Socket(AF_INET, SOCK_STREAM, 0);
    server_sockaddr.sin_family = AF_INET;//IPv4
    server_sockaddr.sin_port = htons(7777);//端口
    server_sockaddr.sin_addr.s_addr = INADDR_ANY;//本主机的任意IP都可以使用

    //端口复用 解决服务端关闭等待2MSL期间内端口被占用的问题
    int opt = 1;
    setsockopt(s_fd,SOL_SOCKET,SO_REUSEPORT,(void*)&opt,sizeof(opt));

    Bind(s_fd,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr));
    printf("bind success!\n");

    Listen(s_fd,5);
    printf("listen success!\n");
    struct sockaddr_in client_sockaddr;
    socklen_t client_sockaddr_len = sizeof(client_sockaddr);
    int c_fd;
    int i = 0;
    while(1){
        c_fd = Accept(s_fd,(struct sockaddr *)&client_sockaddr,&client_sockaddr_len);

        ts[i].cliaddr = client_sockaddr;
        ts[i].connfd = c_fd;
        pthread_create(&tid,NULL,do_work,(void*)&ts[i]);
        pthread_detach(tid);
        i++;
    }
    return 0;
}
